<?php
/**
 * @Name: TokenJwt.php
 * @Author: yashuai<1762910894@qq.com>
 */

namespace HugCode\PhpUnits\Frame\Cipher;

use Firebase\JWT\JWT;
use HugCode\PhpUnits\Frame\Code\ConstCode;

abstract class TokenJwt
{

    abstract public function getNodeList(int $userId);

    abstract public function nodeRelationPower();

    /**
     * @Desc   获取用户id
     *
     * @param string $token
     * @return array|boolean
     * @throws \Exception
     * @author yashuai<1762910894@qq.com>
     */
    public function id(string $token = '')
    {
        $jwtData = $this->decodeToken($token);
        if (empty($jwtData)) {
            return false;
        }
        $jti    = _array_field($jwtData, 'jti');
        $userId = _array_field($jwtData, 'user');
        $iat    = _array_field($jwtData, 'iat', '');
        if (empty($jti) || empty($userId) || $jti != md5($userId . $iat)) {
            return false;
        }

        // 验证有效期
        $newTime = time();
//        $expire  = _array_field($jwtData, 'expire', 0);
//        if ($expire && ($iat + $expire) < $newTime) {
//            _throw('', 107005);
//        }

        return [
            'UserID'  => $userId,
            'Params'  => _array_field($jwtData, 'params', []),
            'Delayed' => ($iat + 1800) < $newTime ? 1 : 0,  // 半小时
        ];
    }

    /**
     * @Desc   解密token
     * @param string $token
     * @return false|array
     * @author yashuai<1762910894@qq.com>
     */
    protected function decodeToken(string $token = '')
    {
        if (empty($token)) {
            return false;
        }
        try {
            $data = JWT::decode($token, env("AUTH_CODE", '0000'), ['HS256']);
            return json_decode(json_encode($data), true);
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * @Desc 生成用户Token
     * @param int $userId
     * @param int $expire 过期时间
     * @param array $params 额外参数
     * @return string
     * @author yashuai<1762910894@qq.com>
     */
    public function createToken(int $userId = 0, int $expire = 86400, array $params = [])
    {
        $newTime = time();
        $payload = [
            'jti'    => md5($userId . $newTime),
            'user'   => $userId,
            'iat'    => $newTime,
            'expire' => $expire, // 有效期
            'params' => $params
        ];

        return JWT::encode($payload, env("AUTH_CODE", '0000'));
    }

    /**
     * @Desc   验证用户菜单权限
     *         注：关联权限为 实际的控制器名 实际方法名（驼峰转中划线），不是路由路径
     * @param array $user
     * @return bool
     * @author yashuai<1762910894@qq.com>
     */
    public function validatorNodePower(array $user)
    {
        if ($user['IsSuper'] == ConstCode::IS_YES) {
            return true;
        }
        list($data, $dataInfo) = $this->nodeRelationPower();

        $actionName = _controller_action();
        $event      = implode('.', $actionName);
        // 在关联权限中设置权限
        if (_array_field($data, $event) == 'allow' || _array_field($data, $actionName[0] . ".*") == 'allow') {
            return true;
        }
        // 在数据库内设置权限
        $nodeList = $this->getNodeList($user['UserID']);
        if (in_array($event, $nodeList)
            || (in_array($actionName[0], $dataInfo)
                && $event == $actionName[0] . ".info"
                && in_array($actionName[0] . ".index", $nodeList))) {
            return true;
        } else {
            $dataKeys = array_keys($data);
            if (!in_array($event, $dataKeys) && !in_array($actionName[0] . ".*", $dataKeys)) {
                return false;
            } else {
                $likeNodeList = array_merge(
                    _array_field($data, $event, []), _array_field($data, $actionName[0] . ".*", [])
                );
                if (is_array($likeNodeList)) {
                    return !empty(array_intersect($likeNodeList, $nodeList));
                }

                return in_array($likeNodeList, $nodeList);
            }
        }
    }


}
